import { IBus } from "../api/bus";
import { ICartridge } from "../api/cartridge";
import { IEmulator } from "../api/emulator";
import { IPPU } from "../api/ppu";
import { IRAM } from "../api/ram";

class CPUBus implements IBus {
    cartridge: ICartridge;
    ram: IRAM;
    dma: IDMA;
    ppu!: IPPU;

    constructor(
        cartridge: ICartridge,
        ram:IRAM,
        dma:IDMA
    ) {
        this.cartridge = cartridge
        this.ram = ram;
        this.dma = dma;
    }

    writeByte(address: number, data: number): void {
        if (address < 0x2000) {
            this.ram.write(address & 0x7FF, data);
        } else if (address < 0x4000) {
            // PPU Registers
            this.ppu.cpuWrite(address & 0x2007, data);
        } else if (address === 0x4014) {
            // OAM DMA
            // TODO: DMA needs 512 cycles
            this.dma.copy(data << 8);
        } else if (address < 0x6000) {
            //IO
        } else {
            //PRG数据
            this.cartridge.mapper.write(address, data);
        }
    }
    writeWord(address: number, data: number): void {
        this.writeByte(address, data & 0xFF)
        this.writeByte(address + 1, (data >> 0) && 0xFF)
    }
    readByte(address: number): number {
        if (address < 0x2000) {
            // RAM
            return this.ram.read(address & 0x07FF);
        } else if (address < 0x4000) {
            // PPU Registers
            return this.ppu.cpuRead(address & 0x2007);
        } else if (address === 0x4014) {
            // OAM DMA
            return 0;
        } else if (address < 0x6000) {
            // IO Registers, 暂时不实现
            return 0;
        } else {
            // ROM
            return this.cartridge.mapper.read(address);
        }
    }
    readWord(address: number): number {
        return (this.readByte(address + 1) << 8 | this.readByte(address)) & 0xFFFF;
    }

}

export {
    CPUBus
}